package user

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"end/config"
	"end/entry"
	"end/httpEntry"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

type userRegister struct {
	Name     string `json:"name" binding:"required"`
	Phone    string `json:"phoneNumber" binding:"required"`
	IdNumber string `json:"idNumber" binding:"required"`
	Password string `json:"password" binding:"required"`
	OpenID   string `json:"openid" binding:"required"`
}

type userRegister2 struct {
	AccessToken string `json:"accessToken" binding:"required"`
	Code        string `json:"code" binding:"required"`
	JsCode      string `json:"jsCode" binding:"required"`
}

type SuccessResponse struct {
	Code  string     `json:"code"`
	Msg   string     `json:"msg"`
	IsFee int        `json:"isFee"`
	SeqNo string     `json:"seqNo"`
	Data  PersonData `json:"data"`
}

type PersonData struct {
	Birthday string `json:"birthday"`
	Gender   int    `json:"gender"`
	Age      int    `json:"age"`
	Province string `json:"province"`
	Result   int    `json:"result"`
}

type PhoneNumberResponse struct {
	PhoneInfo struct {
		PhoneNumber string `json:"phoneNumber"`
	} `json:"phone_info"`
}

type PhoneNumberRequest struct {
	Code string `json:"code"`
}

func Register(r *gin.Engine) {
	type WechatSessionResponse struct {
		OpenID string `json:"openid"`
		// 根据需要，可以添加其他字段，例如 session_key, unionid 等
	}

	r.POST("/user/register", func(c *gin.Context) {
		var userInfo userRegister
		if err := c.ShouldBind(&userInfo); err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		var user entry.User
		_ = copier.Copy(&user, &userInfo)

		// 通过name、IDNumber验证身份证信息
		correct, err := IdentityCorrect(userInfo.Name, userInfo.IdNumber)
		if !correct {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10004,
				Error: err.Error(),
			})
			return
		}

		// 验证全部通过，注册成功
		user.CreateTime = time.Now()
		user.UpdateTime = time.Now()
		user.Integral = 0
		user.Password = md5Encrypt(user.Password)
		user.IdNumber = userInfo.IdNumber
		user.Age = 18
		user.PoliticalOutlook = "群众"
		if err := config.GetDb().Create(&user).Error; err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10014,
				Error: httpEntry.ERROR10014,
			})
			return
		}

		token, additionals := config.CreateToken(user.ID)
		userResponse := LoginResponse{
			Code:    200,
			Message: "登录成功",
			Token:   token,
			Type:    additionals,
		}
		c.JSON(http.StatusOK, userResponse)

	})

	r.POST("/user/register2", func(c *gin.Context) {
		var userInfo userRegister2
		if err := c.ShouldBind(&userInfo); err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}
		var user entry.User

		url := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appID, appSecret, userInfo.JsCode)
		// 发起HTTP GET请求
		resp, err := http.Get(url)
		if err != nil {
			return
		}
		defer func(Body io.ReadCloser) {
			err := Body.Close()
			if err != nil {

			}
		}(resp.Body)
		// 读取响应内容
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10006,
				Error: httpEntry.ERROR10006,
			})
			return
		}

		// 解析JSON数据
		var wechatResp WechatSessionResponse
		err = json.Unmarshal(body, &wechatResp)

		url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + userInfo.AccessToken
		requestData := PhoneNumberRequest{
			Code: userInfo.Code,
		}

		// 将请求数据转换为JSON
		jsonData, err := json.Marshal(requestData)

		// 发起HTTP POST请求
		resp, err = http.Post(url, "application/json", bytes.NewBuffer(jsonData))
		defer func(Body io.ReadCloser) {
			err := Body.Close()
			if err != nil {

			}
		}(resp.Body)

		// 读取响应内容
		body, err = ioutil.ReadAll(resp.Body)

		// 解析JSON数据
		var phoneResp PhoneNumberResponse
		err = json.Unmarshal(body, &phoneResp)

		// 验证全部通过，注册成功
		user.Name = "用户"
		user.CreateTime = time.Now()
		user.UpdateTime = time.Now()
		user.Integral = 0
		user.Age = 18
		user.PoliticalOutlook = "群众"
		user.OpenID = wechatResp.OpenID
		user.Phone = phoneResp.PhoneInfo.PhoneNumber

		if err := config.GetDb().Create(&user).Error; err != nil {
			c.JSON(http.StatusOK, httpEntry.BaseResponse{
				Code:  10014,
				Error: httpEntry.ERROR10014,
			})
			return
		}

		token, additionals := config.CreateToken(user.ID)
		userResponse := LoginResponse{
			Code:    200,
			Message: "登录成功",
			Token:   token,
			Type:    additionals,
		}
		c.JSON(http.StatusOK, userResponse)
	})
}

// IdentityCorrect 验证姓名与身份证号是否匹配
func IdentityCorrect(name string, idcard string) (correct bool, errMsg error) {
	url := "http://smrz.qianshutong.com/web/interface/grsfyz"
	appcode := "204f856a12854050be9372deace07ab8"
	var jsonData = []byte(fmt.Sprintf("idcard=%s&name=%s", idcard, name))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return false, err
	}

	req.Header.Set("Authorization", "APPCODE "+appcode)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return false, err
	}
	defer func(Body io.ReadCloser) {
		err := Body.Close()
		if err != nil {
			fmt.Println("Error closing response body:", err)
		}
	}(resp.Body)

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return false, fmt.Errorf("读取错误")
	}
	fmt.Println(string(body))
	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return false, fmt.Errorf("返回错误")
	}
	var value = ""
	if result["data"] == nil {
		return false, fmt.Errorf("身份证格式错误")
	}
	value = result["data"].(string)
	if strings.Contains(value, `"result":2`) {
		return false, fmt.Errorf("实名错误")
	}
	if strings.Contains(value, `"result":1`) {
		return true, nil
	}
	return false, fmt.Errorf("意外错误")
}

func md5Encrypt(str string) string {
	hash := md5.Sum([]byte(str))
	encryptedStr := hex.EncodeToString(hash[:])
	return encryptedStr
}
